$import( "SmitearWebGL.Events.Event" );
$import( "SmitearWebGL.Events.FileLoadEvent" );
$import( "SmitearWebGL.IO.ImageLoader" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeEntity" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeImage" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeSource" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeAnimationClip" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeCamera" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeController" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeMaterial" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeEffect" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeGeometry" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeNode");
$import( "SmitearWebGL.Objects.Parser.Collada.DaePhysicsScene" );
$import( "SmitearWebGL.Objects.Parser.Collada.DaeVisualScene" );

SmitearWebGL.Objects.Parser.Collada.DaeDocument = SmitearWebGL.Objects.Parser.Collada.DaeEntity.extend(
{
	/******** constructor ********/

	init : function( data )
	{
		/******** public property ********/

		this.version = "";
		this.baseUrl = "";
		this.COLLADA = data;
		this.yUp = 0;
		this.sources = null;
		this.animation_clips = null;
		this.animations = null;
		this.animatables = null;
		this.controllers = null;
		this.effects = null;
		this.images = null;
		this.materials = null;
		this.geometries = null;
		this.physics_scenes = null;
		this.visual_scenes = null;
		this.nodes = null;
		this.cameras = null;
		this.materialSymbolToTarget = null;
		this.materialTargetToSymbol = null;

		/******** private property ********/

		this._loadingImage = null;
		this._queuedImages = null;
		this._waitingSources = null;

		this._super( this, data );
		this._registClass( "SmitearWebGL.Objects.Parser.Collada.DaeDocument" );
	}
	,

	/******** public method ********/

	read : function( node )
	{
		this.version = node.getAttribute( SmitearWebGL.Objects.Parser.Collada.Const.DAE_VERSION_ATTRIBUTE );

		$LOG( "collada version: " + this.version );

		this.asset = new SmitearWebGL.Objects.Parser.Collada.DaeAsset( this, this.getNode(this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_ASSET_ELEMENT) );

		if( this.asset.contributors && this.asset.contributors[0].author )
		$LOG( "author: " + this.asset.contributors[0].author );
		$LOG( "created: " + this.asset.created );
		$LOG( "modified: " + this.asset.modified );
		$LOG( "y-up: " + this.asset.yUp );
		$LOG( "unit_meter: " + this.asset.unit_meter );
		$LOG( "unit_name: " + this.asset.unit_name );

		if( this.asset.yUp == SmitearWebGL.Objects.Parser.Collada.Const.DAE_Y_UP )
			this.yUp = SmitearWebGL.Objects.Parser.Collada.DaeDocument.Y_UP;
		else
			this.yUp = SmitearWebGL.Objects.Parser.Collada.DaeDocument.Z_UP;

		this._buildMaterialTable();
		this._readLibImages();
		this._readSources();
	}
	,
	readAfterSources : function()
	{
		this.readLibAnimationClips();
		this.readLibAnimations();
		this.readLibCameras();
		this.readLibControllers();
		this.readLibMaterials();
		this.readLibEffects();
		this.readLibGeometries();
		this.readLibNodes();
		this.readLibPhysicsScenes();
		this.readLibVisualScenes();
		this.readScene();
	}
	,
	readNextSource : function()
	{
		if( this._waitingSources.length != 0 )
		{
			var node = this._waitingSources.pop();
			var source = new SmitearWebGL.Objects.Parser.Collada.DaeSource( this.document, node );

			this.sources[source.id] = source;
		}

		return ( this._waitingSources.length > 0 );
	}
	,
	readNextImage : function()
	{
		if( this._loadingImage == null && this._queuedImages.length )
		{
			this._loadingImage = this._queuedImages.pop();

			this.loadImage();
		}
		else
		{
			this.dispatchEvent( new SmitearWebGL.Events.Event( SmitearWebGL.Events.Event.COMPLETE ) );
		}
		return ( this._loadingImage == null && this._queuedImages.length > 0);
	}
	,
	loadImage : function()
	{
		var loader = new SmitearWebGL.IO.ImageLoader();
		loader.contentLoaderInfo.addEventListener( SmitearWebGL.Events.FileLoadEvent.FILE_LOAD_COMPLETE, this, this.onImageLoadComplete);
		loader.contentLoaderInfo.addEventListener( SmitearWebGL.Events.FileLoadEvent.LOAD_ERROR, this, this.onImageLoadError);

		var path = this._loadingImage.init_from;
		var imageUrl = this._loadingImage.init_from;

		if ( this.baseUrl != "" )
		{
			path = this._buildImagePath( this.baseUrl, imageUrl );
		}

		loader.load( path );
	}
	,
	onImageLoadComplete : function( e )
	{
		var contentLoaderInfo = e.sender;
		contentLoaderInfo.removeEventListener( SmitearWebGL.Events.FileLoadEvent.FILE_LOAD_COMPLETE, this.onImageLoadComplete);
		contentLoaderInfo.removeEventListener( SmitearWebGL.Events.FileLoadEvent.LOAD_ERROR, this.onImageLoadError);
		
		if( contentLoaderInfo.content )
			this._loadingImage.htmlElement = contentLoaderInfo.content;

		this._loadingImage = null;

		this.readNextImage();
	}
	,
	onImageLoadError : function( e )
	{
		var contentLoaderInfo = e.sender;
		contentLoaderInfo.removeEventListener( SmitearWebGL.Events.FileLoadEvent.FILE_LOAD_COMPLETE, this.onImageLoadComplete);
		contentLoaderInfo.removeEventListener( SmitearWebGL.Events.FileLoadEvent.LOAD_ERROR, this.onImageLoadError);
		
		$ERROR( "Image source: " + e.url + " load failed!" );
		
		this._loadingImage = null;

		this.readNextImage();
	}
	,
	destroy : function()
	{
		this._super();

		var element;

		if ( this.sources )
		{
			for (element in this.sources)
			{
				this.sources[element].destroy();
			}
			this.sources = null;
		}

		if ( this.images )
		{
			for (element in this.images)
			{
				this.images[element].destroy();
			}
			this.images = null;
		}
		this.COLLADA = null;
	}
	,
	getWaitingSources : function()
	{
		return this._waitingSources;
	}
	,
	readLibAnimationClips : function()
	{
		this.animation_clips = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_ANIMATION_CLIP_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_ANIMCLIP_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeAnimationClip( this, list[i] );
				this.animation_clips[ ent.id ] = ent;
			}
		}
	}
	,
	readLibAnimations : function()
	{
		this.animations = {};
		this.animatables = {};
		
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_ANIMATION_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_ANIMATION_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var animation = new SmitearWebGL.Objects.Parser.Collada.DaeAnimation( this, list[i] );
		
				this.readAnimation( animation );
			}
		}
	}
	,
	readAnimation : function( animation ) 
	{
		if(animation.channels && animation.channels.length)
		{
			this.animations[ animation.id ] = animation;
		}
	
		for ( var child in animation.animations )
		{
			readAnimation( animation.animations[child] );
		}
	}
	,
	readLibCameras : function()
	{
		this.cameras = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_CAMERA_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_CAMERA_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeCamera( this, list[i] );
				this.cameras[ ent.id ] = ent;
			}
		}
	}
	,
	readLibControllers : function()
	{
		this.controllers = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_CONTROLLER_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_CONTROLLER_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeController( this, list[i] );
				this.controllers[ ent.id ] = ent;
			}
		}
	}
	,
	readLibMaterials : function()
	{
		this.materials = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_MATERIAL_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_MATERIAL_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeMaterial( this, list[i] );
				this.materials[ ent.id ] = ent;
			}
		}
	}
	,
	readLibEffects : function()
	{
		this.effects = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_EFFECT_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_EFFECT_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeEffect( this, list[i] );
				this.effects[ ent.id ] = ent;
			}
		}
	}
	,
	readLibGeometries : function()
	{
		this.geometries = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_GEOMETRY_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_GEOMETRY_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var geometry = new SmitearWebGL.Objects.Parser.Collada.DaeGeometry( this, list[i], false );
				this.geometries[ geometry.id ] = geometry;
//				if(geometry.mesh)
//				{
//	
//				}
			}
		}
	}
	,
	readLibNodes : function()
	{
		this.nodes = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_NODE_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_NODE_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var node = new SmitearWebGL.Objects.Parser.Collada.DaeNode( this, list[i] );
				this.nodes[ node.id ] = node;
			}
		}
	}
	,
	readLibPhysicsScenes : function()
	{
		this.physics_scenes = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_PSCENE_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_PHYSICS_SCENE_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaePhysicsScene( this, list[i] );
				this.physics_scenes[ ent.id ] = ent;
			}
		}
	}
	,
	readLibVisualScenes : function()
	{
		this.visual_scenes = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_VSCENE_ELEMENT );
		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_VSCENE_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var ent = new SmitearWebGL.Objects.Parser.Collada.DaeVisualScene( this, list[i], this.yUp );
				this.visual_scenes[ ent.id ] = ent;
				this.vscene = ent;
			}
		}
	}
	,
	readScene : function()
	{
		var sceneNode = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_SCENE_ELEMENT );
		if( sceneNode )
		{
			var vsceneNode = this.getNode( sceneNode, SmitearWebGL.Objects.Parser.Collada.Const.DAE_INSTANCE_VSCENE_ELEMENT );
			if( vsceneNode )
			{
				var vurl = this.getAttribute( vsceneNode, SmitearWebGL.Objects.Parser.Collada.Const.DAE_URL_ATTRIBUTE );
				if( this.visual_scenes[vurl].isTypeOf("SmitearWebGL.Objects.Parser.Collada.DaeVisualScene") )
				{
					$LOG( "found visual scene: " + vurl );
	
					this.vscene = this.visual_scenes[ vurl ];
	
					$LOG( " -> frameRate: " + this.vscene.getFrameRate() );
					$LOG( " -> startTime: " + this.vscene.getStartTime() );
					$LOG( " -> endTime: " + this.vscene.getEndTime() );
				}
			}
	
			var psceneNode = this.getNode( sceneNode, SmitearWebGL.Objects.Parser.Collada.Const.DAE_INSTANCE_PHYSICS_SCENE_ELEMENT );
			if( psceneNode )
			{
				var purl = this.getAttribute( psceneNode, SmitearWebGL.Objects.Parser.Collada.Const.DAE_URL_ATTRIBUTE );
				if( this.physics_scenes[purl].isTypeOf("SmitearWebGL.Objects.Parser.Collada.DaePhysicsScene") )
				{
					$LOG( "found physics scene: " + purl );
					this.pscene = this.physics_scenes[ purl ];
				}
			}
		}
	}
	,

	/******** private method ********/

	_buildMaterialTable : function()
	{
		materialSymbolToTarget = {};
		materialTargetToSymbol = {};

		var nodes = this.COLLADA.getElementsByTagName( SmitearWebGL.Objects.Parser.Collada.Const.DAE_INSTANCE_MATERIAL_ELEMENT );

		for ( var i = 0; i < nodes.length; ++ i )
		{
			var child = nodes[i];
			var target = this.getAttribute(child, SmitearWebGL.Objects.Parser.Collada.Const.DAE_TARGET_ATTRIBUTE);
			var symbol = this.getAttribute(child, SmitearWebGL.Objects.Parser.Collada.Const.DAE_SYMBOL_ATTRIBUTE);

			materialSymbolToTarget[symbol] = target;
			materialTargetToSymbol[target] = symbol;
		}
	}
	,
	_readLibImages : function()
	{
		this.images = {};
		var library = this.getNode( this.COLLADA, SmitearWebGL.Objects.Parser.Collada.Const.DAE_LIBRARY_IMAGE_ELEMENT );

		this._queuedImages = [];

		if( library )
		{
			var list = this.getNodeList( library, SmitearWebGL.Objects.Parser.Collada.Const.DAE_IMAGE_ELEMENT );
			for ( var i = 0; i < list.length; ++ i )
			{
				var image = new SmitearWebGL.Objects.Parser.Collada.DaeImage( this, list[i] );
				this.images[ image.id ] = image;
				this._queuedImages.push( image );
			}
		}
	}
	,
	_readSources : function()
	{
		var nodes = this.COLLADA.getElementsByTagName( SmitearWebGL.Objects.Parser.Collada.Const.DAE_SOURCE_ELEMENT );
		var list = [];
		for ( var i = 0; i < nodes.length; ++ i )
		{
			if ( nodes[i].hasAttribute( "id" ) )
			list.push( nodes[i] );
		}

		var element;

		this.numSources = list.length;
		this.sources = {};
		this._waitingSources = [];

		for ( var i = 0; i < list.length; ++ i )
		{
			var element = list[i];

			var source = new SmitearWebGL.Objects.Parser.Collada.DaeSource( this, element );
			this.sources[source.id] = source;
		}
	}
	,
	_buildImagePath : function( meshFolderPath, imgPath )
	{
		var baseParts = meshFolderPath.split("/");
		var imgParts = imgPath.split("/");

		while( baseParts[0] == "." )
		baseParts.shift();

		while( imgParts[0] == "." )
		imgParts.shift();

		while( imgParts[0] == ".." )
		{
			imgParts.shift();
			baseParts.pop();
		}

		var imgUrl = baseParts.length > 1 ? baseParts.join("/") : (baseParts.length?baseParts[0]:"");

		imgUrl = imgUrl != "" ? imgUrl + "/" + imgParts.join("/") : imgParts.join("/");

		return imgUrl;
	}
}
);

SmitearWebGL.Objects.Parser.Collada.DaeDocument.X_UP = 0;
SmitearWebGL.Objects.Parser.Collada.DaeDocument.Y_UP = 1;
SmitearWebGL.Objects.Parser.Collada.DaeDocument.Z_UP = 2;